/**
 * 
 */
package com.xpec.c4.service.group.datalayer.infinispan;

import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.infinispan.Cache;
import org.infinispan.config.Configuration;
import org.infinispan.context.Flag;
import org.infinispan.lifecycle.ComponentStatus;
import org.infinispan.manager.DefaultCacheManager;
import org.infinispan.remoting.transport.Address;
import org.infinispan.remoting.transport.jgroups.JGroupsTransport;
import org.jgroups.conf.ProtocolStackConfigurator;

import com.xpec.c4.service.group.OperationType;
import com.xpec.c4.service.group.datalayer.IDataManager;
import com.xpec.c4.service.group.datalayer.IShareMap;
import com.xpec.c4.service.module.ModuleServer;
import com.xpec.c4.service.module.ServerProperties;
import com.xpec.c4.service.utility.Utility;

/**
 * 共享管理器
 * 
 * @author lipeilin
 * @2011-1-25 下午03:58:04
 * 
 */
@Deprecated
public class InfinispanDataManager implements IDataManager {

	private static final Log log = LogFactory
			.getLog(InfinispanDataManager.class);

	/**
	 * 读优化常量
	 */
	private static final String READ_OPTIMIZE = "ReadOptimize";

	/**
	 * 写优化常量
	 */
	private static final String WRITE_OPTIMIZE = "WriteOptimize";

	private DefaultCacheManager cm;

	@SuppressWarnings("unchecked")
	private HashMap<String, InfinispanShareMap> sharemapList = new HashMap<String, InfinispanShareMap>();

	/**
	 * 单例
	 */
	public InfinispanDataManager() {
		try {
			String cacheConfigFile = "infinispan-config.xml";
			// URL resource = getClass().getClassLoader().getResource(
			// cacheConfigFile);
			// if (resource == null) {
			// resource = new URL(cacheConfigFile);
			// }
			URL resource = Utility.getUrl(cacheConfigFile);
			log.info("file path:" + resource.getPath());
			log.info("resource.openStream():" + resource.openStream());
			cm = new DefaultCacheManager(resource.openStream(), false);
			String clusterName = "ShareDataManager";
			cm.getGlobalConfiguration().fluent().transport().clusterName(
					clusterName);
			String nodeName = ModuleServer.getInstance().getName()
					+ "_ShareDataManager";
			cm.getGlobalConfiguration().fluent().transport().nodeName(nodeName);
			cm.getGlobalConfiguration().fluent().transport()
					.machineId(nodeName);
			// .setTransportNodeName("ShareDataManager");

			// 加载配置数据
			ProtocolStackConfigurator configurator = null;
			String protocol = ServerProperties.getString(
					"group_datalayer_protocol", "TCP");

			// TCP
			if (protocol.toUpperCase().equals("TCP")) {
				/*
				configurator = JgroupUtitly.getJgroupsTCPConfigurator(
						ServerProperties.groupIP,
						ServerProperties.groupDatalayerPort);
				*/
			}
			
			// TCP PING
			else if (protocol.toUpperCase().equals("TCPPING")) {
				// configurator = JgroupUtitly.getJgroupsTcpPingDataConfigurator();
			}
			// UDP
			else {
				/*
				configurator = JgroupUtitly.getJgroupsUDPConfigurator(
						ServerProperties.groupIP,
						ServerProperties.groupDatalayerPort);
				*/
			}

			cm.getGlobalConfiguration().fluent().transport().addProperty(
					JGroupsTransport.CONFIGURATION_STRING,
					configurator.getProtocolStackString());

			//cm.start();
			log.info("ProtocolStackString:"
					+ configurator.getProtocolStackString());
			log.info("ClusterName:" + cm.getClusterName());
			log.info("Members:" + cm.getMembers());
			log.info("CacheNames:" + cm.getCacheNames());
			log.info("Coordinator:" + cm.getCoordinator());
			/*
			log.info("Infinispan channel: " + cm.getAddress() + " "
					+ ServerProperties.groupDatalayerPort);
			*/
		} catch (Exception e) {
			log.error("DefaultCacheManager can not create", e);
		}

		ArrayList<String> cacheNames = new ArrayList<String>(cm.getCacheNames());
		log.info("start caches:" + cacheNames);
		cm.startCaches(cacheNames.toArray(new String[1]));
		
		Set<String> nameCaches = cm.getCacheNames();
		Iterator<String> iterator = nameCaches.iterator();
		while (iterator.hasNext()) {
			String nameCahe = iterator.next();
			getShareMap(nameCahe);
			//caches.put(nameCahe, embeddedCacheManager.getCache(nameCahe));
		}

		//try {
			//Thread.sleep(60000);
		//} catch (InterruptedException e) {
		//}

//		for (String name : cacheNames) {
//			try {
//				Thread.sleep(500);
//			} catch (InterruptedException e1) {
//				e1.printStackTrace();
//			}
//			InfinispanShareMap<?, ?> map = (InfinispanShareMap<?, ?>) getShareMap(name);
//			while (!map.getCache().getStatus().equals(ComponentStatus.RUNNING)) {
//				try {
//					Thread.sleep(500);
//				} catch (InterruptedException e) {
//					e.printStackTrace();
//				}
//				log.info("waiting for cache(" + name + ") to run!"
//						+ map.getCache().getStatus());
//			}
//		}

		// cm.startCache();
		// initGroup();

		// while (!cm.getStatus().equals(ComponentStatus.RUNNING)) {
		// try {
		// Thread.sleep(1000);
		// } catch (InterruptedException e) {
		// e.printStackTrace();
		// }
		// log.info("waiting for cache manager to run!" + cm.getStatus());
		// }

		log.info("cache manager status:" + cm.getStatus());

		// getShareMap();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.xpec.c4.service.group.IGroupManager#getShareMap(java.lang.String)
	 */
	@SuppressWarnings("unchecked")
	public <K, V> IShareMap<K, V> getShareMap(String name) {

		InfinispanShareMap<K, V> map = sharemapList.get(name);
		if (map == null) {
			log.info("init cache:" + name);

			Cache<K, V> cache = getCache(name);
			// 不加锁
			cache = cache.getAdvancedCache().withFlags(Flag.SKIP_LOCKING);

			log.info(name + " cache status:" + cache.getStatus());

			map = new InfinispanShareMap<K, V>(cache, name);
			sharemapList.put(name, map);

		}
		return map;
	}

	public <V, K> Cache<K, V> getCache(String name) {
		Cache<K, V> cache = cm.getCache(name);
		// 不加锁
		cache = cache.getAdvancedCache().withFlags(Flag.SKIP_LOCKING);
		//cache.start();
		return cache;
	}

	@SuppressWarnings("unchecked")
	public <K, V> IShareMap<K, V> initShareMap(String name) {

		InfinispanShareMap<K, V> map = sharemapList.get(name);
		if (map == null) {
			Cache<K, V> cache = cm.getCache(name);
			// 不加锁
			cache = cache.getAdvancedCache().withFlags(Flag.SKIP_LOCKING);
			cache.start();

			log.info(name + " cache status:" + cache.getStatus());

			map = new InfinispanShareMap<K, V>(cache, name);
			sharemapList.put(name, map);

			log.info("init cache:" + name);
		}
		return map;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.xpec.c4.service.group.IGroupManager#getShareMap(java.lang.String)
	 */
	@SuppressWarnings("unchecked")
	public <K, V> IShareMap<K, V> getShareMap(String name, long lifespan) {
		InfinispanShareMap<K, V> map = sharemapList.get(name);
		if (map == null) {
			Cache<K, V> cache = cm.getCache(name);

			// 不加锁
			cache = cache.getAdvancedCache().withFlags(Flag.SKIP_LOCKING);

			Configuration config = new Configuration();
			config.setExpirationLifespan(lifespan);
			config.setL1Lifespan(lifespan);
			cm.defineConfiguration(name, READ_OPTIMIZE, config);

			cache.start();

			log.info(name + " cache status:" + cache.getStatus());

			map = new InfinispanShareMap<K, V>(cache, name);
			sharemapList.put(name, map);

			// cache.putAsync((K) "1", (V) "1");

			log.info("init cache:" + name);
		}
		return map;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.xpec.c4.service.group.IGroupManager#getShareMap(java.lang.String,
	 * com.xpec.c4.service.group.OperationType)
	 */
	@SuppressWarnings("unchecked")
	public <K, V> IShareMap<K, V> getShareMap(String name, OperationType type) {
		InfinispanShareMap<K, V> map = sharemapList.get(name);
		if (map == null) {
			// switch (type) {
			// case READ_OPTIMIZE:
			// cm
			// .defineConfiguration(name, READ_OPTIMIZE,
			// new Configuration());
			// break;
			// case WRITE_OPTIMIZE:
			// cm.defineConfiguration(name, WRITE_OPTIMIZE,
			// new Configuration());
			// break;
			// }
			Cache<K, V> cache = cm.getCache(name);
			// 不加锁
			cache = cache.getAdvancedCache().withFlags(Flag.SKIP_LOCKING);
			if (cache.getStatus() != ComponentStatus.RUNNING) {
				cache.start();
			}

			log.info(name + " cache status:" + cache.getStatus());

			map = new InfinispanShareMap<K, V>(cache, name);
			sharemapList.put(name, map);

			log.info("init " + type + " cache:" + name);
		}
		return map;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.xpec.c4.service.group.IGroupManager#getShareMap()
	 */
	@SuppressWarnings("unchecked")
	public <K, V> IShareMap<K, V> getShareMap() {
		String name = null;
		InfinispanShareMap<K, V> map = sharemapList.get(name);
		if (map == null) {
			Cache<K, V> cache = cm.getCache();
			// 不加锁
			cache = cache.getAdvancedCache().withFlags(Flag.SKIP_LOCKING);
			map = new InfinispanShareMap<K, V>(cache, name);

			sharemapList.put(name, map);
			log.info("init default cache.");
		}
		return map;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.xpec.c4.service.group.IGroupManager#getMembers()
	 */
	public List<Address> getMembers() {
		log.info("MachineId:"
				+ cm.getGlobalConfiguration().getTransportNodeName());
		return cm.getMembers();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.xpec.c4.service.group.IGroupManager#isCoordinator()
	 */
	public boolean isCoordinator() {
		return cm.isCoordinator();
	}

	/**
	 * 加载编辑的静态数据资源
	 * 
	 */
	private void initGroup() {

		// JobExecutor.execute(new InitGroup());

//		for (String name : GroupProperties.cacheNames) {
//			log.info("Init Group Cache:" + name);
//			getShareMap(name);
//			try {
//				Thread.sleep(1);
//			} catch (InterruptedException e) {
//				e.printStackTrace();
//			}
//		}

	}

	@Override
	public void stop() {
		cm.stop();
	}
}

class InitGroup implements Runnable {

	private static final Log log = LogFactory.getLog(InitGroup.class);

	public static boolean done = false;

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Runnable#run()
	 */
	@Override
	public void run() {
/*
		for (String name : GroupProperties.cacheNames) {
			log.info("Init Group Cache:" + name);
			IShareMap<Object, Object> map = ServerGroup.getDataManager()
					.getShareMap(name);
			try {
				Thread.sleep(1);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

		log.info("Init Group Cache done!");
*/		
		done = true;

	}

}
